﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;
using System.Web.Routing;
using MyAMS.Utility;
using MyAMS.WebServer.Models;
using MyAMS.WebServer.Models.Extensions;
using MyAMS.WebServer.Repositories;

namespace MyAMS.WebServer.Routing
{
    class NodeConstraint : IRouteConstraint
    {
        private readonly INodeRepository nodeRepository;
        private static readonly string parsedUriName = "ParsedUri";
        private static readonly string nodeName = "Node";

        public NodeConstraint(INodeRepository nodeRepository)
        {
            this.nodeRepository = nodeRepository;
        }

        #region IRouteConstraint 成员

        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            bool isSuccessed = false;
            Uri uri = httpContext.Request.Url;
            Node currentNode = nodeRepository.Get(uri.Host);
            if (currentNode != null)
            {
                Queue<string> paths = new Queue<string>(uri.AbsolutePath.Split('/'));
                int originalCount = paths.Count;
                paths.Enqueue(String.Empty); // (5he11) 为了下边递归算法的需要, 最后需要有一个空节                
                currentNode = Parse(currentNode, paths);
                isSuccessed = paths.Count == 0;
                if (isSuccessed)
                {
                    values.Add(parsedUriName, uri);
                }
                else
                {
                    string parsedUri = uri.Scheme + "://" + uri.Host;
                    string[] originalPaths = uri.AbsolutePath.Split('/');
                    for (int i = 0; i < originalCount - paths.Count; i++)
                    {
                        if (!String.IsNullOrEmpty(originalPaths[i]))
                        {
                            parsedUri += "/" + originalPaths[i];
                        }
                    }
                    values.Add(parsedUriName, new Uri(parsedUri));
                }
            }
            values.Add(nodeName, currentNode);
            return isSuccessed;
        }

        #endregion


        private static Node Parse(Node currentNode, Queue<string> paths)
        {
            if (paths.Count == 0)
            {
                return currentNode;                                                     // 如果路径被完全解析, 说明被完全解析, 返回最后解析到的节点
            }

            string path = paths.Dequeue();

            if (String.IsNullOrEmpty(path))
            {
                return Parse(currentNode, paths);                                       // 路径节点为空是不正确的, 忽略进入下次递归
            }

            foreach (BaseNode node in currentNode.Children)
            {
                if (node is Node)
                {
                    Node nd = node as Node;
                    List<RoutingRole> roles = node.GetRolesWithInheritance("Node", currentNode.IsOwned);
                    roles.InsertRange(0, nd.GetRoles("Node"));
                    foreach (RoutingRole role in roles)
                    {
                        // 判断当前规则是否为动态解析规则
                        if (role.IsDynamicRole())
                        {
                            string propertyName = role.Uri.Substring(1, role.Uri.Length - 2);
                            PropertyInfo propertyInfo = node.GetType().GetProperty(propertyName);
                            if (propertyInfo != null)
                            {
                                object value = propertyInfo.GetValue(node, null);
                                Helper.Assert(value != null, "");//Resource.Get("Error.InvalidNodePropertyValueFound"));
                                if (String.Compare(path.UrlDecode(), value.ToString(), true) == 0)
                                {
                                    return Parse(nd, paths) as Node;                  // 如果成功解析当前节, 则进入下一节的解析
                                }
                            }
                        }
                        else
                        {
                            if (String.Compare(path.UrlDecode(), role.Uri, true) == 0)
                            {
                                return Parse(nd, paths) as Node;                      // 如果成功解析当前节, 则进入下一节的解析
                            }
                        }
                    }
                }
            }

            return currentNode;                                             // 如果在当前节什么都解析不到的话, 则说明到此为止无法再解析, 返回当前解析了的节点
        }
    }
}
